/*
 * Copyright (c) 2010, Katholieke Universiteit Leuven
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of the Katholieke Universiteit Leuven nor the names of
 *       its contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef __LOOCI_GWAPI_INTROSPECTION_H__
#define __LOOCI_GWAPI_INTROSPECTION_H__

#include <stdbool.h>
#include <inttypes.h>

/**
 * The component states.
 */
enum {
  COMPONENT_STATE_NONE = 0,
  COMPONENT_STATE_ACTIVE = 1,
  COMPONENT_STATE_DEACTIVATED = 2,
};

#define WIRE_NODEID_LENGTH 40

/**
 * Data type for an outgoing wire
 */
struct looci_outgoing_wire {
  char nodeID[WIRE_NODEID_LENGTH];
};

/**
 * Data type for an incoming wire
 */
struct looci_incoming_wire {
  char nodeID[WIRE_NODEID_LENGTH];
  uint8_t componentID;
};

/**
 * Get the components of a given type on a given node.
 *
 * @param componentType The type of the components.
 * @param nodeID The node identifier (IPv6 address) of the node.
 * @param buffer A buffer where the component ids will be copied to.
 * @param size Pointer to a variable that will contain the number of component
 *	       ids in the buffer after the call. This variable must be initialized
 *	       to the maximum number of component ids the buffer can hold.
 *
 * @return 'true' if successful, 'false' otherwise
 *
 * @note if the return value is false and *size > 0, the buffer was too small to hold all component ids.
 *       if the return value is false and *size == 0, another error occured.
 *       if the return value is true and *size == 0, there are no components with the given type.
 */
bool looci_get_component_ids_by_type(char * componentType, char * nodeID, uint8_t * buffer, size_t * size);

/**
 * Get the components on a given node.
 *
 * @param nodeID The node identifier (IPv6 address) of the node.
 * @param buffer A buffer where the component ids will be copied to.
 * @param size Pointer to a variable that will contain the number of component
 *	       ids in the buffer after the call. This variable must be initialized
 *	       to the maximum number of component ids the buffer can hold.
 *
 * @return 'true' if successful, 'false' otherwise
 *
 * @note if the return value is false and *size > 0, the buffer was too small to hold all component ids.
 *       if the return value is false and *size == 0, another error occured.
 *       if the return value is true and *size == 0, there are no components.
 */
bool looci_get_component_ids(char * nodeID, uint8_t * buffer, size_t * size);

/**
 * Get the type of a given component on a given node.
 *
 * @param componentId The component identifier.
 * @param nodeID The node identifier (IPv6 address) of the node.
 * @param type A string buffer where the type will be copied to.
 * @param maxlen The maximum length of a string that the buffer can hold.
 *
 * @return 'true' is successful, 'false' otherwise
 */
bool looci_get_componenttype(uint8_t componentID, char * nodeID, char * type, size_t maxlen);

/**
 * Introspect the state of a component.
 *
 * @param componentID The component identifier.
 * @param nodeID The node identifier (IPv6 address) of the node
 *               the component is on.
 *
 * @return The state of the component. COMPONENT_STATE_NONE if an error of 
 *         some kind occurred.
 */
uint8_t looci_get_state(uint8_t componentID, char * nodeID);

/**
 * Introspect the interfaces of a component.
 *
 * @param componentID The component identifier.
 * @param nodeID The node identifier (IPv6 address) of the node
 *               the component is on.
 * @param buffer A buffer where the interfaces will be copied to
 * @param size Pointer to variable that will contain the number of interfaces in the buffer
 *             after the call. This variable must be initialized to the maximum number of interfaces
 *             the buffer can hold.
 *
 * @return 'true' if successful, 'false' otherwise
 * @note if the return value is false and *size > 0, the buffer was too small to hold all interfaces.
 *       if the return value is false and *size==0, an other error occured.
 *       if the return value is true and *size==0, the component has no interfaces
 *
 * @TODO Should this be something else than uint8_t for event types.
 */
bool looci_get_interfaces(uint8_t componentID, char * nodeID, uint8_t * buffer, size_t * size);

/**
 * Introspect the receptacles of a component.
 *
 * @param componentID The component identifier.
 * @param nodeID The node identifier (IPv6 address) of the node
 *               the component is on.
 * @param buffer A buffer where the receptacles will be copied to
 * @param size Pointer to variable that will contain the number of receptacles in the buffer
 *             after the call. This should be initialized to the maximum number of receptacles
 *             the buffer can hold.
 *
 * @return 'true' if successful, 'false' otherwise
 * 
 * @note if the return value is false and *size > 0, the buffer was too small to hold all receptacles.
 *       if the return value is false and *size==0, an other error occured.
 *       if the return value is true and *size==0, the component has no receptacles.
 *
 * @TODO Should this be something else than uint8_t for event types.
 * @TODO Can we avoid returning dynamically allocated memory?
 */
bool looci_get_receptacles(uint8_t componentID, char * nodeID, uint8_t * buffer, size_t * size);

/**
 * Introspect the outgoing wires for a specific interface.
 *
 * @param interfaceEvent The event type of the interface.
 * @param componentID The component identifier of the interface.
 * @param nodeID The identifier of the node (IPv6 address).
 * @param buffer A buffer where the outgoing wires will be written to.
 * @param size A pointer to a variable that will hold the number of wires in the buffer
 *	       after the call. This variable must be initialized to the maximum size of the buffer.
 * 
 * @return 'true' if succesful, 'false' otherwise
 *
 * @note if the return value is false and *size > 0, the buffer was too small to hold all wires.
 *       if the return value is false and *size == 0, another error occured.
 *       if the return value is true and *size == 0, there are no outgoing remote wires for the given interface.
 */
bool looci_get_outgoing_wires(uint8_t interfaceEvent, uint8_t componentID, char * nodeID, struct looci_outgoing_wire * buffer, size_t * size);

/**
 * Introspect the incoming wires for component.
 *
 * @param interfaceEvent The event type of the interface that is wired to a receptacle of the component.
 * @param componentID The component identifier.
 * @param nodeID The identifier of the node (IPv6 address).
 * @param buffer A buffer where the wires will be written to.
 * @param size A pointer to a variable that will hold the number of wires in the buffer
 *             after the call. This variable must be initialized to the maximum size of the buffer.
 *
 * @return 'true' if succesful, 'false' otherwise
 *
 * @note if the return value is false and *size > 0, the buffer was too small to hold all wires.
 *       if the return value is false and *size == 0, another error occured.
 *       if the return value is true and *size == 0, there are no incoming remote wires for the given component and given interfaceEvent
 */
bool looci_get_incoming_wires(uint8_t interfaceEvent, uint8_t componentID, char * nodeID, struct looci_incoming_wire * buffer, size_t * size);

/**
 * Introspect the local wires for a specific interface.
 *
 * @param interfaceEvent The event type of the interface.
 * @param componentID The component identifier of the interface.
 * @param nodeID The node identifier (IPv6 address).
 * @param buffer A buffer where the destination component ids will be copied to.
 * @param size Pointer to a variable that will contain the number of component
 *	       ids in the buffer after the call. This variable must be initialized
 *	       to the maximum number of component ids the buffer can hold.
 *
 * @return 'true' if successful, 'false' otherwise
 *
 * @note if the return value is false and *size > 0, the buffer was too small to hold all destination component ids.
 *       if the return value is false and *size == 0, another error occured.
 *       if the return value is true and *size == 0, there are no local wires for the given interface.
 */
bool looci_get_local_wires(uint8_t interfaceEvent, uint8_t componentID, char * nodeID, uint8_t * buffer, size_t * size);

#endif // __LOOCI_GWAPI_INTROSPECTION_H__
